import winston from 'winston';
import chalk from 'chalk';
import dayjs from 'dayjs';
import 'winston-daily-rotate-file';
import { ConfigurationService } from './configuration.service';

const logDir = 'logs';

export const winstonConfigFactory = (config: ConfigurationService) => {
  return {
    level: config.app.nodeEnv === 'dev' ? 'debug' : 'info',
    transports: [
      new winston.transports.Console({
        format: winston.format.combine(
          winston.format.ms(),
          winston.format.timestamp(),
          winston.format.printf(
            ({ context, level, message, ms, timestamp }) => {
              const appStr = chalk.green(`[Nest]`);
              const pidStr = chalk.green(`${process.pid}  -`);
              const timestampStr = dayjs(timestamp as Date).format(
                'YYYY/MM/DD HH:mm:ss',
              );
              let levelStr = level.toUpperCase();
              switch (level) {
                case 'error':
                  levelStr = chalk.red(levelStr);
                  break;
                case 'warn':
                  levelStr = chalk.yellow(levelStr);
                  break;
                case 'info':
                  levelStr = chalk.green(levelStr);
                  break;
                default:
                  levelStr = chalk.green(levelStr);
                  break;
              }
              const contextStr = chalk.yellow(`[${context}]`);
              const messageStr = chalk.green(
                typeof message === 'object' ? JSON.stringify(message) : message,
              );
              const msStr = chalk.yellow(`${ms}`);

              return `${appStr} ${pidStr} ${timestampStr}     ${levelStr} ${contextStr} ${messageStr} ${msStr}`;
            },
          ),
        ),
      }),
      new winston.transports.DailyRotateFile({
        dirname: logDir,
        filename: 'application-%DATE%.log',
        datePattern: 'YYYY-MM-DD',
        maxSize: '20m',
        maxFiles: '30d',
        format: winston.format.combine(
          winston.format.ms(),
          winston.format.timestamp(),
          winston.format.printf(
            ({ context, level, message, ms, timestamp }) => {
              const pidStr = `${process.pid}  -`;
              const timestampStr = dayjs(timestamp as Date).format(
                'YYYY/MM/DD HH:mm:ss',
              );
              let levelStr = level.toUpperCase();
              const contextStr = `[${context}]`;
              const messageStr =
                typeof message === 'object' ? JSON.stringify(message) : message;

              return `${pidStr} ${timestampStr}     ${levelStr} ${contextStr} ${messageStr}`;
            },
          ),
        ),
      }),
      new winston.transports.DailyRotateFile({
        dirname: logDir,
        filename: 'error-%DATE%.log',
        datePattern: 'YYYY-MM-DD',
        level: 'error',
        maxSize: '20m',
        maxFiles: '30d',
        format: winston.format.combine(
          winston.format.ms(),
          winston.format.timestamp(),
          winston.format.printf(
            ({ context, level, message, ms, timestamp }) => {
              const pidStr = `${process.pid}  -`;
              const timestampStr = dayjs(timestamp as Date).format(
                'YYYY/MM/DD HH:mm:ss',
              );
              let levelStr = level.toUpperCase();
              const contextStr = `[${context}]`;
              const messageStr =
                typeof message === 'object' ? JSON.stringify(message) : message;

              return `${pidStr} ${timestampStr}     ${levelStr} ${contextStr} ${messageStr}`;
            },
          ),
        ),
      }),
    ],
  };
};
